{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "# Internal Datastructure: Bus branch model, Admittance and Jacobian Matrix\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This jupyter notebooks explains how to access and interpret the internal datastructure with relevant matrices."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Internal Datastructure\n",
    "\n",
    "We use the simple example network from the create_simple tutorial as an example for how to access internal calculation parameters:\n",
    "\n",
    "<img src=\"pics/example_network_simple.png\">\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "This pandapower network includes the following parameter tables:\n",
      "   - bus (7 elements)\n",
      "   - load (1 element)\n",
      "   - sgen (1 element)\n",
      "   - gen (1 element)\n",
      "   - switch (8 elements)\n",
      "   - shunt (1 element)\n",
      "   - ext_grid (1 element)\n",
      "   - line (4 elements)\n",
      "   - trafo (1 element)\n"
     ]
    }
   ],
   "source": [
    "import pandapower as pp\n",
    "import pandapower.networks as nw\n",
    "\n",
    "net = nw.example_simple()\n",
    "print(net)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First, we run a power flow in this network:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "pp.runpp(net)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "When a power flow is carried out, the element based grid model is translated into a bus-branch model. That bus-branch model is stored in a data structure that is based on the PYPOWER/MATPOWER casefile (with some extensions). This ppc can be accesed after power flow:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'baseMVA': 1,\n",
       " 'version': 2,\n",
       " 'bus': array([[ 0.00000000e+00,  3.00000000e+00,  0.00000000e+00,\n",
       "          0.00000000e+00,  0.00000000e+00,  0.00000000e+00,\n",
       "          1.00000000e+00,  1.02000000e+00,  0.00000000e+00,\n",
       "          1.10000000e+02,  1.00000000e+00,  2.00000000e+00,\n",
       "          0.00000000e+00,  0.00000000e+00,  0.00000000e+00],\n",
       "        [ 1.00000000e+00,  1.00000000e+00,  0.00000000e+00,\n",
       "          0.00000000e+00,  0.00000000e+00,  9.60000000e-01,\n",
       "          1.00000000e+00,  1.02082951e+00,  3.24135661e-02,\n",
       "          1.10000000e+02,  1.00000000e+00,  2.00000000e+00,\n",
       "          0.00000000e+00,  0.00000000e+00,  0.00000000e+00],\n",
       "        [ 2.00000000e+00,  1.00000000e+00,  0.00000000e+00,\n",
       "          0.00000000e+00,  0.00000000e+00,  0.00000000e+00,\n",
       "          1.00000000e+00,  1.02456241e+00,  1.80284793e+00,\n",
       "          2.00000000e+01,  1.00000000e+00,  2.00000000e+00,\n",
       "          0.00000000e+00,  0.00000000e+00,  0.00000000e+00],\n",
       "        [ 3.00000000e+00,  2.00000000e+00,  0.00000000e+00,\n",
       "          0.00000000e+00,  0.00000000e+00,  0.00000000e+00,\n",
       "          1.00000000e+00,  1.03000000e+00,  1.87045457e+00,\n",
       "          2.00000000e+01,  1.00000000e+00,  2.00000000e+00,\n",
       "          0.00000000e+00,  0.00000000e+00,  0.00000000e+00],\n",
       "        [ 4.00000000e+00,  1.00000000e+00, -8.00000000e-01,\n",
       "          2.90000000e+00,  0.00000000e+00,  0.00000000e+00,\n",
       "          1.00000000e+00,  1.02320534e+00,  1.95222438e+00,\n",
       "          2.00000000e+01,  1.00000000e+00,  2.00000000e+00,\n",
       "          0.00000000e+00,  0.00000000e+00,  0.00000000e+00],\n",
       "        [ 5.00000000e+00,  1.00000000e+00,  0.00000000e+00,\n",
       "          0.00000000e+00,  0.00000000e+00,  0.00000000e+00,\n",
       "          1.00000000e+00,  1.03000700e+00,  1.86983253e+00,\n",
       "          2.00000000e+01,  1.00000000e+00,  1.10000000e+00,\n",
       "          9.00000000e-01,  0.00000000e+00,  0.00000000e+00],\n",
       "        [ 6.00000000e+00,  4.00000000e+00,  0.00000000e+00,\n",
       "          0.00000000e+00,  0.00000000e+00,  0.00000000e+00,\n",
       "          1.00000000e+00,             nan,             nan,\n",
       "          1.10000000e+02,  1.00000000e+00,  2.00000000e+00,\n",
       "          0.00000000e+00,  0.00000000e+00,  0.00000000e+00],\n",
       "        [ 7.00000000e+00,  4.00000000e+00,  0.00000000e+00,\n",
       "          0.00000000e+00,  0.00000000e+00,  0.00000000e+00,\n",
       "          1.00000000e+00,             nan,             nan,\n",
       "          2.00000000e+01,  1.00000000e+00,  2.00000000e+00,\n",
       "          0.00000000e+00,  0.00000000e+00,  0.00000000e+00]]),\n",
       " 'branch': array([[ 0.00000000e+00+0.j        ,  1.00000000e+00+0.j        ,\n",
       "          4.95867769e-05+0.j        ,  1.19008264e-04+0.j        ,\n",
       "          5.47391104e+00+0.j        ,  2.50000000e+02+0.j        ,\n",
       "          2.50000000e+02+0.j        ,  2.50000000e+02+0.j        ,\n",
       "          1.00000000e+00+0.j        ,  0.00000000e+00+0.j        ,\n",
       "          1.00000000e+00+0.j        , -3.60000000e+02+0.j        ,\n",
       "          3.60000000e+02+0.j        , -6.74111530e+00+0.j        ,\n",
       "         -7.14688297e+00+0.j        ,  6.74416214e+00+0.j        ,\n",
       "          1.45450502e+00+0.j        ,  0.00000000e+00+0.j        ,\n",
       "          0.00000000e+00+0.j        ,  0.00000000e+00+0.j        ,\n",
       "          0.00000000e+00+0.j        ,  0.00000000e+00+0.j        ,\n",
       "          0.00000000e+00+0.j        ],\n",
       "        [ 2.00000000e+00+0.j        ,  3.00000000e+00+0.j        ,\n",
       "          6.10000000e-04+0.j        ,  5.60000000e-04+0.j        ,\n",
       "          7.64035333e-02+0.j        ,  2.50000000e+02+0.j        ,\n",
       "          2.50000000e+02+0.j        ,  2.50000000e+02+0.j        ,\n",
       "          1.00000000e+00+0.j        ,  0.00000000e+00+0.j        ,\n",
       "          1.00000000e+00+0.j        , -3.60000000e+02+0.j        ,\n",
       "          3.60000000e+02+0.j        , -5.97238973e+00+0.j        ,\n",
       "         -3.48162502e+00+0.j        ,  5.99999998e+00+0.j        ,\n",
       "          3.42634241e+00+0.j        ,  0.00000000e+00+0.j        ,\n",
       "          0.00000000e+00+0.j        ,  0.00000000e+00+0.j        ,\n",
       "          0.00000000e+00+0.j        ,  0.00000000e+00+0.j        ,\n",
       "          0.00000000e+00+0.j        ],\n",
       "        [ 3.00000000e+00+0.j        ,  5.00000000e+00+0.j        ,\n",
       "          5.19662500e-03+0.j        ,  3.25500000e-03+0.j        ,\n",
       "          4.17831823e-03+0.j        ,  2.50000000e+02+0.j        ,\n",
       "          2.50000000e+02+0.j        ,  2.50000000e+02+0.j        ,\n",
       "          1.00000000e+00+0.j        ,  0.00000000e+00+0.j        ,\n",
       "          1.00000000e+00+0.j        , -3.60000000e+02+0.j        ,\n",
       "          3.60000000e+02+0.j        ,  2.40626916e-08+0.j        ,\n",
       "         -4.43279288e-03+0.j        ,  5.89955431e-14+0.j        ,\n",
       "         -1.27190902e-14+0.j        ,  0.00000000e+00+0.j        ,\n",
       "          0.00000000e+00+0.j        ,  0.00000000e+00+0.j        ,\n",
       "          0.00000000e+00+0.j        ,  0.00000000e+00+0.j        ,\n",
       "          0.00000000e+00+0.j        ],\n",
       "        [ 4.00000000e+00+0.j        ,  2.00000000e+00+0.j        ,\n",
       "          7.62500000e-04+0.j        ,  7.00000000e-04+0.j        ,\n",
       "          9.55044167e-02+0.j        ,  2.50000000e+02+0.j        ,\n",
       "          2.50000000e+02+0.j        ,  2.50000000e+02+0.j        ,\n",
       "          1.00000000e+00+0.j        ,  0.00000000e+00+0.j        ,\n",
       "          1.00000000e+00+0.j        , -3.60000000e+02+0.j        ,\n",
       "          3.60000000e+02+0.j        ,  8.00000000e-01+0.j        ,\n",
       "         -2.90000000e+00+0.j        , -7.93618189e-01+0.j        ,\n",
       "          2.80573774e+00+0.j        ,  0.00000000e+00+0.j        ,\n",
       "          0.00000000e+00+0.j        ,  0.00000000e+00+0.j        ,\n",
       "          0.00000000e+00+0.j        ,  0.00000000e+00+0.j        ,\n",
       "          0.00000000e+00+0.j        ],\n",
       "        [ 1.00000000e+00+0.j        ,  2.00000000e+00+0.j        ,\n",
       "          1.63923679e-04+0.j        ,  4.79726336e-03+0.j        ,\n",
       "         -1.05000908e-02-0.01399964j,  2.50000000e+02+0.j        ,\n",
       "          2.50000000e+02+0.j        ,  2.50000000e+02+0.j        ,\n",
       "          1.00000000e+00+0.j        ,  0.00000000e+00+0.j        ,\n",
       "          1.00000000e+00+0.j        , -3.60000000e+02+0.j        ,\n",
       "          3.60000000e+02+0.j        , -6.74416214e+00+0.j        ,\n",
       "         -4.54095852e-01+0.j        ,  6.76600792e+00+0.j        ,\n",
       "          6.75887284e-01+0.j        ,  0.00000000e+00+0.j        ,\n",
       "          0.00000000e+00+0.j        ,  0.00000000e+00+0.j        ,\n",
       "          0.00000000e+00+0.j        ,  0.00000000e+00+0.j        ,\n",
       "          0.00000000e+00+0.j        ]]),\n",
       " 'gen': array([[ 0.00000000e+00, -6.74111530e+00, -7.14688297e+00,\n",
       "          0.00000000e+00,  0.00000000e+00,  1.02000000e+00,\n",
       "          1.00000000e+00,  1.00000000e+00,  1.00000000e+09,\n",
       "         -1.00000000e+09,  0.00000000e+00,  0.00000000e+00,\n",
       "          0.00000000e+00,  0.00000000e+00,  0.00000000e+00,\n",
       "          0.00000000e+00,  0.00000000e+00,  0.00000000e+00,\n",
       "          0.00000000e+00,  0.00000000e+00,  0.00000000e+00],\n",
       "        [ 3.00000000e+00,  6.00000000e+00,  3.42190962e+00,\n",
       "          3.00000000e+00, -3.00000000e+00,  1.03000000e+00,\n",
       "                     nan,  1.00000000e+00,  1.00000000e+09,\n",
       "         -1.00000000e+09,  0.00000000e+00,  0.00000000e+00,\n",
       "          0.00000000e+00,  0.00000000e+00,  0.00000000e+00,\n",
       "          0.00000000e+00,  0.00000000e+00,  0.00000000e+00,\n",
       "          0.00000000e+00,  0.00000000e+00,  0.00000000e+00]]),\n",
       " 'internal': {'Ybus': <6x6 sparse matrix of type '<class 'numpy.complex128'>'\n",
       "  \twith 16 stored elements in Compressed Sparse Row format>,\n",
       "  'Yf': <5x6 sparse matrix of type '<class 'numpy.complex128'>'\n",
       "  \twith 10 stored elements in Compressed Sparse Row format>,\n",
       "  'Yt': <5x6 sparse matrix of type '<class 'numpy.complex128'>'\n",
       "  \twith 10 stored elements in Compressed Sparse Row format>,\n",
       "  'branch_is': array([ True,  True,  True,  True,  True]),\n",
       "  'gen_is': array([ True,  True]),\n",
       "  'DLF': array([], dtype=complex128),\n",
       "  'buses_ord_bfs_nets': array([], dtype=float64),\n",
       "  'ref_gens': array([0]),\n",
       "  'J': <9x9 sparse matrix of type '<class 'numpy.float64'>'\n",
       "  \twith 41 stored elements in Compressed Sparse Row format>,\n",
       "  'Vm_it': None,\n",
       "  'Va_it': None},\n",
       " 'success': True,\n",
       " 'et': 0.012522697448730469,\n",
       " 'iterations': 3}"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net._ppc"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For information on how this datastructure is defined, please refer to the MATPOWER documentation."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Note:** For linear power flow (DC load flow) 'Ybus' is no longer created, but 'Bbus' as a new 'internal' key."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 8402.77777778+0.j, -8402.77777778+0.j,     0.        +0.j,\n",
       "            0.        +0.j,     0.        +0.j,     0.        +0.j],\n",
       "       [-8402.77777778+0.j,  8611.22995659+0.j,  -208.45217882+0.j,\n",
       "            0.        +0.j,     0.        +0.j,     0.        +0.j],\n",
       "       [    0.        +0.j,  -208.45217882+0.j,  3422.7378931 +0.j,\n",
       "        -1785.71428571+0.j, -1428.57142857+0.j,     0.        +0.j],\n",
       "       [    0.        +0.j,     0.        +0.j, -1785.71428571+0.j,\n",
       "         2092.93394777+0.j,     0.        +0.j,  -307.21966206+0.j],\n",
       "       [    0.        +0.j,     0.        +0.j, -1428.57142857+0.j,\n",
       "            0.        +0.j,  1428.57142857+0.j,     0.        +0.j],\n",
       "       [    0.        +0.j,     0.        +0.j,     0.        +0.j,\n",
       "         -307.21966206+0.j,     0.        +0.j,   307.21966206+0.j]])"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pp.rundcpp(net)\n",
    "net._ppc['internal']['Bbus'].A"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Nodal Point Admittance Matrix\n",
    "\n",
    "The nodal point admittance matrix is saved in the ppc and can be accessed directly:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[ 2983.234714  -7157.02635809j, -2983.234714  +7159.76331361j,\n",
       "             0.           +0.j        ,     0.           +0.j        ,\n",
       "             0.           +0.j        ,     0.           +0.j        ],\n",
       "        [-2983.234714  +7159.76331361j,  2990.35626947-7364.28068082j,\n",
       "            -7.11455564 +208.20907269j,     0.           +0.j        ,\n",
       "             0.           +0.j        ,     0.           +0.j        ],\n",
       "        [    0.           +0.j        ,    -7.11455564 +208.20907269j,\n",
       "          1608.40491554-1678.15899439j,  -889.60186671 +816.68368091j,\n",
       "          -711.68149336 +653.34694473j,     0.           +0.j        ],\n",
       "        [    0.           +0.j        ,     0.           +0.j        ,\n",
       "          -889.60186671 +816.68368091j,  1027.81021222 -903.21268537j,\n",
       "             0.           +0.j        ,  -138.20834551  +86.56929539j],\n",
       "        [    0.           +0.j        ,     0.           +0.j        ,\n",
       "          -711.68149336 +653.34694473j,     0.           +0.j        ,\n",
       "           711.68149336 -653.29919252j,     0.           +0.j        ],\n",
       "        [    0.           +0.j        ,     0.           +0.j        ,\n",
       "             0.           +0.j        ,  -138.20834551  +86.56929539j,\n",
       "             0.           +0.j        ,   138.20834551  -86.56720623j]])"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pp.runpp(net)\n",
    "net._ppc[\"internal\"][\"Ybus\"].todense()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that the nodal point admittance matrix is given in per unit values."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Jacobian Matrix\n",
    "\n",
    "The jacobian Matrix J in the last iteration step is also stored in the ppc and can be accessed:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[ 9.54796437e+02,  0.00000000e+00, -8.62952855e+02,\n",
       "          0.00000000e+00, -9.18435819e+01,  0.00000000e+00,\n",
       "         -9.15296717e+02,  0.00000000e+00, -1.42353628e+02],\n",
       "        [ 0.00000000e+00,  7.67426447e+03, -2.17432759e+02,\n",
       "          0.00000000e+00,  0.00000000e+00,  3.05264392e+03,\n",
       "         -1.38258923e+01,  0.00000000e+00,  0.00000000e+00],\n",
       "        [-8.60737361e+02, -2.17892547e+02,  1.76161072e+03,\n",
       "         -6.82980812e+02,  0.00000000e+00, -6.95203313e-01,\n",
       "          1.64791123e+03, -7.30904816e+02,  0.00000000e+00],\n",
       "        [ 0.00000000e+00,  0.00000000e+00, -6.86871047e+02,\n",
       "          6.86871047e+02,  0.00000000e+00,  0.00000000e+00,\n",
       "         -7.26450958e+02,  7.28978162e+02,  0.00000000e+00],\n",
       "        [-9.18403982e+01,  0.00000000e+00,  0.00000000e+00,\n",
       "          0.00000000e+00,  9.18403982e+01,  0.00000000e+00,\n",
       "          0.00000000e+00,  0.00000000e+00,  1.42355564e+02],\n",
       "        [ 0.00000000e+00, -3.11622898e+03,  1.41654896e+01,\n",
       "          0.00000000e+00,  0.00000000e+00,  7.51767502e+03,\n",
       "         -2.12220120e+02,  0.00000000e+00,  0.00000000e+00],\n",
       "        [ 9.39812512e+02,  7.09684055e-01, -1.68838791e+03,\n",
       "          7.47865712e+02,  0.00000000e+00, -2.13446561e+02,\n",
       "          1.71937864e+03, -6.67491446e+02,  0.00000000e+00],\n",
       "        [ 0.00000000e+00,  0.00000000e+00,  7.44294349e+02,\n",
       "         -7.44294349e+02,  0.00000000e+00,  0.00000000e+00,\n",
       "         -6.70404297e+02,  6.65624993e+02,  0.00000000e+00],\n",
       "        [ 1.46627228e+02,  0.00000000e+00,  0.00000000e+00,\n",
       "          0.00000000e+00, -1.46627228e+02,  0.00000000e+00,\n",
       "          0.00000000e+00,  0.00000000e+00,  8.91648289e+01]])"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net._ppc[\"internal\"][\"J\"].todense()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The jacobian matrix is also given in per unit values."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Mapping the Buses\n",
    "\n",
    "The pandapower indices are not equal to the ppc indices for several reasons. Some buses are fused together in case of closed bus-bus switches and auxiliary buses are created for elements like extended wards or three winding transformers. There is however a mapping between pandapower indices and ppc indices that is created during the conversion to keep track of the dependencies that is also stored in the net:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 1, 1, 2, 2, 3, 4])"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net._pd2ppc_lookups[\"bus\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To get a ppc index from the pandapower index, simply call the lookup like this:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n"
     ]
    }
   ],
   "source": [
    "pandapower_bus_idx = 3\n",
    "ppc_index = net._pd2ppc_lookups[\"bus\"][pandapower_bus_idx]\n",
    "print(ppc_index)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As you can see, pandapower bus index 3 corresponds to ppc bus index 2. So if we would like to find the diagonal entry of the Ybus matrix for bus 2, we could now access it with that internal index:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(2990.35626947-7364.28068082j)"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Ybus = net._ppc[\"internal\"][\"Ybus\"]\n",
    "int_idx = net._pd2ppc_lookups[\"bus\"][ppc_index]\n",
    "Ybus[int_idx, int_idx]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can also see that some buses are mapped to the same internal bus, such as bus 1 and bus 2:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "1\n"
     ]
    }
   ],
   "source": [
    "print(net._pd2ppc_lookups[\"bus\"][1])\n",
    "print(net._pd2ppc_lookups[\"bus\"][2])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "That is because buses 1 and 2 are connected by a closed bus-bus switch and are therefore represented internally as the same bus:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "bus           1\n",
       "element       2\n",
       "et            b\n",
       "type         CB\n",
       "closed     True\n",
       "name       None\n",
       "z_ohm         0\n",
       "Name: 0, dtype: object"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net.switch.loc[0]"
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
